﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace Dot5Demo.Utils
{
    public class FileCheckUtil
    {
        public enum CheckSumType
        {
            MD5,
            SHA1,
            SHA256,
            SHA384,
            SHA512,
            CRC32,
            CRC64,
        }

        public static string GetFileChecksum(string file, CheckSumType type = CheckSumType.MD5, bool toUpper = true)
        {
            if (string.IsNullOrEmpty(file))
                return null;
            if (!File.Exists(file))
                return "";
            switch (type)
            {
                case CheckSumType.MD5:
                    return GetFile_MD5(file, toUpper);
                case CheckSumType.SHA1:
                    return GetFile_SHA1(file, toUpper);
                case CheckSumType.SHA256:
                    return GetFile_SHA256(file, toUpper);
                case CheckSumType.SHA384:
                    return GetFile_SHA384(file, toUpper);
                case CheckSumType.SHA512:
                    return GetFile_SHA512(file, toUpper);
                case CheckSumType.CRC32:
                    break;
                case CheckSumType.CRC64:
                    break;
                default:
                    break;
            }
            return null;
        }

        public static string GetFile_MD5(string fileName, bool toUpper = true)
        {
            string res = null;
            using (var fs = File.OpenRead(fileName))
            {
                using (var md5 = MD5.Create())
                {
                    byte[] hashBytes = md5.ComputeHash(fs);
                    res = BitConverter.ToString(hashBytes).Replace("-", "");
                }
            }
            return toUpper ? res.ToUpper() : res.ToLower();
        }

        public static string GetFile_SHA1(string file, bool toUpper = true)
        {
            try
            {
                using (var reader = File.OpenRead(file))
                {
                    var csp = new SHA1CryptoServiceProvider();
                    byte[] bytHash = csp.ComputeHash(reader);
                    csp.Clear();
                    //根据计算得到的Hash码翻译为SHA-1码
                    string sHash = "", sTemp = "";
                    for (int counter = 0; counter < bytHash.Length; counter++)
                    {
                        long i = bytHash[counter] / 16;
                        if (i > 9)
                        {
                            sTemp = ((char)(i - 10 + 0x41)).ToString();
                        }
                        else
                        {
                            sTemp = ((char)(i + 0x30)).ToString();
                        }
                        i = bytHash[counter] % 16;
                        if (i > 9)
                        {
                            sTemp += ((char)(i - 10 + 0x41)).ToString();
                        }
                        else
                        {
                            sTemp += ((char)(i + 0x30)).ToString();
                        }
                        sHash += sTemp;
                    }
                    //根据大小写规则决定返回的字符串
                    return toUpper ? sHash : sHash.ToLower();
                }
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

        public static string GetFile_SHA256(string file, bool toUpper = true)
        {
            try
            {
                using (var reader = File.OpenRead(file))
                {
                    var csp = new SHA256CryptoServiceProvider();
                    byte[] bytHash = csp.ComputeHash(reader);
                    csp.Clear();
                    //根据计算得到的Hash码翻译为SHA-1码
                    string sHash = "", sTemp = "";
                    for (int counter = 0; counter < bytHash.Length; counter++)
                    {
                        long i = bytHash[counter] / 16;
                        if (i > 9)
                        {
                            sTemp = ((char)(i - 10 + 0x41)).ToString();
                        }
                        else
                        {
                            sTemp = ((char)(i + 0x30)).ToString();
                        }
                        i = bytHash[counter] % 16;
                        if (i > 9)
                        {
                            sTemp += ((char)(i - 10 + 0x41)).ToString();
                        }
                        else
                        {
                            sTemp += ((char)(i + 0x30)).ToString();
                        }
                        sHash += sTemp;
                    }
                    //根据大小写规则决定返回的字符串
                    return toUpper ? sHash : sHash.ToLower();
                }
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

        public static string GetFile_SHA384(string file, bool toUpper = true)
        {
            try
            {
                using (var reader = File.OpenRead(file))
                {
                    var csp = new SHA384CryptoServiceProvider();
                    byte[] bytHash = csp.ComputeHash(reader);
                    csp.Clear();
                    //根据计算得到的Hash码翻译为SHA-1码
                    string sHash = "", sTemp = "";
                    for (int counter = 0; counter < bytHash.Length; counter++)
                    {
                        long i = bytHash[counter] / 16;
                        if (i > 9)
                        {
                            sTemp = ((char)(i - 10 + 0x41)).ToString();
                        }
                        else
                        {
                            sTemp = ((char)(i + 0x30)).ToString();
                        }
                        i = bytHash[counter] % 16;
                        if (i > 9)
                        {
                            sTemp += ((char)(i - 10 + 0x41)).ToString();
                        }
                        else
                        {
                            sTemp += ((char)(i + 0x30)).ToString();
                        }
                        sHash += sTemp;
                    }
                    //根据大小写规则决定返回的字符串
                    return toUpper ? sHash : sHash.ToLower();
                }
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

        public static string GetFile_SHA512(string file, bool toUpper = true)
        {
            try
            {
                using (var reader = File.OpenRead(file))
                {
                    var csp = new SHA512CryptoServiceProvider();
                    byte[] bytHash = csp.ComputeHash(reader);
                    csp.Clear();
                    //根据计算得到的Hash码翻译为SHA-1码
                    string sHash = "", sTemp = "";
                    for (int counter = 0; counter < bytHash.Length; counter++)
                    {
                        long i = bytHash[counter] / 16;
                        if (i > 9)
                        {
                            sTemp = ((char)(i - 10 + 0x41)).ToString();
                        }
                        else
                        {
                            sTemp = ((char)(i + 0x30)).ToString();
                        }
                        i = bytHash[counter] % 16;
                        if (i > 9)
                        {
                            sTemp += ((char)(i - 10 + 0x41)).ToString();
                        }
                        else
                        {
                            sTemp += ((char)(i + 0x30)).ToString();
                        }
                        sHash += sTemp;
                    }
                    //根据大小写规则决定返回的字符串
                    return toUpper ? sHash : sHash.ToLower();
                }
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

    }
}
